import { Document, Packer, Paragraph, TextRun, Table, TableRow, TableCell, WidthType } from 'docx';
import * as fs from 'fs';
import * as path from 'path';

/**
 * 文档导出辅助类，处理计算结果的文档导出功能
 */
export class DocxHelper {
  /**
   * 导出报告为 docx，包含输入参数和计算结果
   * params: { siteName?: string, inputs: object, results: object }
   */
  static async exportReportDocx(params: any) {
    try {
      const { siteName = '计算报告', inputs = {}, results = {}, author = '' } = params;

      const dateStr = new Date().toLocaleString();

      // 标题样式优化（中英文字体：中文宋体，英文字体 Times New Roman）
      const title = new Paragraph({
        children: [new TextRun({ text: `${siteName}`, bold: true, size: 40, font: { ascii: 'Times New Roman', eastAsia: '宋体' } })],
        spacing: { after: 200 },
        alignment: 'center'
      });
      
      const meta = new Paragraph({
        children: [new TextRun({ text: `生成日期：${dateStr}${author ? '    作者：' + author : ''}`, italics: true, font: { ascii: 'Times New Roman', eastAsia: '宋体' } })],
        spacing: { after: 300 },
        alignment: 'center'
      });
      
      const spacer = new Paragraph({ spacing: { after: 200 } });

      // 输入参数标题
      const inputTitle = new Paragraph({
        children: [new TextRun({ text: '一、输入参数', bold: true, size: 28, font: { ascii: 'Times New Roman', eastAsia: '宋体' } })],
        spacing: { after: 200 }
      });

      // Build inputs table (三列：参数 | 数值 | 单位)
      const inputRows: TableRow[] = [];
      inputRows.push(new TableRow({
        children: [
          new TableCell({
            children: [new Paragraph({
              children: [new TextRun({ text: '参数', bold: true, font: { ascii: 'Times New Roman', eastAsia: '宋体' } })],
              spacing: { after: 100 }
            })],
            width: { size: 4000, type: WidthType.DXA },
            shading: { fill: "E0E0E0" }
          }),
          new TableCell({
            children: [new Paragraph({
              children: [new TextRun({ text: '数值', bold: true, font: { ascii: 'Times New Roman', eastAsia: '宋体' } })],
              spacing: { after: 100 }
            })],
            width: { size: 5000, type: WidthType.DXA },
            shading: { fill: "E0E0E0" }
          }),
          new TableCell({
            children: [new Paragraph({
              children: [new TextRun({ text: '单位', bold: true, font: { ascii: 'Times New Roman', eastAsia: '宋体' } })],
              spacing: { after: 100 }
            })],
            width: { size: 3000, type: WidthType.DXA },
            shading: { fill: "E0E0E0" }
          }),
        ],
        tableHeader: true
      }));

      Object.keys(inputs || {}).forEach((k) => {
        const val = (inputs as any)[k];
        let value = '';
        let unit = '';
        
        // 处理新的参数格式 {value, unit}
        if (val !== null && typeof val === 'object' && ('value' in val || 'unit' in val)) {
          value = val.value !== undefined ? String(val.value) : JSON.stringify(val);
          unit = val.unit || '';
        } else if (val !== null && typeof val === 'object') {
          value = JSON.stringify(val, null, 2);
        } else {
          value = String(val);
        }
        
        inputRows.push(new TableRow({
          children: [
              new TableCell({
                children: [new Paragraph({
                  children: [new TextRun({ text: String(k), font: { ascii: 'Times New Roman', eastAsia: '宋体' } })],
                  spacing: { after: 100 }
                })]
              }),
              new TableCell({
                children: [new Paragraph({
                  children: [new TextRun({ text: value, font: { ascii: 'Times New Roman', eastAsia: '宋体' } })],
                  spacing: { after: 100 }
                })]
              }),
              new TableCell({
                children: [new Paragraph({
                  children: [new TextRun({ text: unit || '', font: { ascii: 'Times New Roman', eastAsia: '宋体' } })],
                  spacing: { after: 100 }
                })]
              }),
          ]
        }));
      });

      const inputsTable = new Table({
        rows: inputRows,
        width: { size: 100, type: WidthType.PERCENTAGE },
        alignment: 'center',
        margins: { top: 100, bottom: 100 },
        columnWidths: [4000, 5000, 3000]
      });

      // 计算结果标题
      const resultTitle = new Paragraph({
        children: [new TextRun({ text: '二、计算结果', bold: true, size: 28, font: { ascii: 'Times New Roman', eastAsia: '宋体' } })],
        spacing: { before: 300, after: 200 }
      });

      // Build results table. Support two shapes:
      // 1) Array of { name, value, unit? }
      // 2) Object map { key: value } or { key: { value, unit } }
      const resultRows: TableRow[] = [];
      resultRows.push(new TableRow({
        children: [
          new TableCell({
            children: [new Paragraph({
              children: [new TextRun({ text: '项目', bold: true, font: { ascii: 'Times New Roman', eastAsia: '宋体' } })],
              spacing: { after: 100 }
            })],
            width: { size: 5000, type: WidthType.DXA },
            shading: { fill: "E0E0E0" }
          }),
          new TableCell({
            children: [new Paragraph({
              children: [new TextRun({ text: '数值', bold: true, font: { ascii: 'Times New Roman', eastAsia: '宋体' } })],
              spacing: { after: 100 }
            })],
            width: { size: 5000, type: WidthType.DXA },
            shading: { fill: "E0E0E0" }
          }),
          new TableCell({
            children: [new Paragraph({
              children: [new TextRun({ text: '单位', bold: true, font: { ascii: 'Times New Roman', eastAsia: '宋体' } })],
              spacing: { after: 100 }
            })],
            width: { size: 2000, type: WidthType.DXA },
            shading: { fill: "E0E0E0" }
          }),
        ],
        tableHeader: true
      }));

      if (Array.isArray(results)) {
        (results as any[]).forEach((it) => {
          const name = it.name ?? '';
          const value = it.value !== undefined ? it.value : (it.display ?? '');
          const unit = it.unit ?? '';
          resultRows.push(new TableRow({
            children: [
              new TableCell({
                children: [new Paragraph({
                  children: [new TextRun({ text: String(name), font: { ascii: 'Times New Roman', eastAsia: '宋体' } })],
                  spacing: { after: 100 }
                })]
              }),
              new TableCell({
                children: [new Paragraph({
                  children: [new TextRun({ text: typeof value === 'object' ? JSON.stringify(value, null, 2) : String(value), font: { ascii: 'Times New Roman', eastAsia: '宋体' } })],
                  spacing: { after: 100 }
                })]
              }),
              new TableCell({
                children: [new Paragraph({
                  children: [new TextRun({ text: String(unit), font: { ascii: 'Times New Roman', eastAsia: '宋体' } })],
                  spacing: { after: 100 }
                })]
              }),
            ]
          }));
        });
      } else {
        Object.keys(results || {}).forEach((k) => {
          const raw = (results as any)[k];
          let value: any = '';
          let unit = '';
          if (raw !== null && typeof raw === 'object' && ('value' in raw || 'unit' in raw)) {
            value = raw.value !== undefined ? raw.value : JSON.stringify(raw);
            unit = raw.unit || '';
          } else if (raw !== null && typeof raw === 'object') {
            value = JSON.stringify(raw, null, 2);
          } else {
            value = String(raw);
          }

          resultRows.push(new TableRow({
            children: [
              new TableCell({
                children: [new Paragraph({
                  children: [new TextRun({ text: String(k), font: { ascii: 'Times New Roman', eastAsia: '宋体' } })],
                  spacing: { after: 100 }
                })]
              }),
              new TableCell({
                children: [new Paragraph({
                  children: [new TextRun({ text: typeof value === 'object' ? JSON.stringify(value, null, 2) : String(value), font: { ascii: 'Times New Roman', eastAsia: '宋体' } })],
                  spacing: { after: 100 }
                })]
              }),
              new TableCell({
                children: [new Paragraph({
                  children: [new TextRun({ text: String(unit), font: { ascii: 'Times New Roman', eastAsia: '宋体' } })],
                  spacing: { after: 100 }
                })]
              }),
            ]
          }));
        });
      }

      const resultsTable = new Table({
        rows: resultRows,
        width: { size: 100, type: WidthType.PERCENTAGE },
        alignment: 'center',
        margins: { top: 100, bottom: 100 },
        columnWidths: [5000, 5000, 2000]
      });

      const doc = new Document({
        sections: [{
          properties: {},
          children: [title, meta, spacer, inputTitle, inputsTable, spacer, resultTitle, resultsTable]
        }],
        styles: {
          default: {
            heading1: {
              run: {
                size: 28,
                bold: true,
                italics: true,
                font: { ascii: 'Times New Roman', eastAsia: '宋体' }
              },
              paragraph: {
                spacing: { after: 120 },
              },
            },
            heading2: {
              run: {
                size: 26,
                bold: true,
                font: { ascii: 'Times New Roman', eastAsia: '宋体' }
              },
              paragraph: {
                spacing: { before: 240, after: 120 },
              },
            },
            document: {
              run: {
                font: { ascii: 'Times New Roman', eastAsia: '宋体' },
                size: 20
              }
            }
          },
          paragraphStyles: [
            {
              id: "normalPara",
              name: "Normal Para",
              basedOn: "Normal",
              next: "Normal",
              quickFormat: true,
              run: {
                size: 20,
                font: { ascii: 'Times New Roman', eastAsia: '宋体' }
              },
              paragraph: {
                spacing: { line: 276, before: 20 * 0.1, after: 20 * 0.1 },
              },
            },
          ]
        }
      });

      const buffer = await Packer.toBuffer(doc);

      const reportsDir = path.resolve(process.cwd(), 'reports');
      if (!fs.existsSync(reportsDir)) fs.mkdirSync(reportsDir, { recursive: true });

      const filename = `${siteName.replace(/[^a-z0-9_\u4e00-\u9fa5]/gi, '_')}_${Date.now()}.docx`;
      const filepath = path.join(reportsDir, filename);
      fs.writeFileSync(filepath, buffer);

      return { success: true, data: filepath };
    } catch (error: any) {
      return { success: false, error: error.message };
    }
  }
}